From 859492d2216cd8fe9924018d5bc738b78603627d Mon Sep 17 00:00:00 2001 From: "cl349@firebug.cl.cam.ac.uk[cl349]" Date: Sat, 2 Apr 2005 21:21:29 +0000 Subject: [PATCH] bitkeeper revision 1.1159.258.88 (424f0cd9Oldi24NGanGDdr82_K9qpQ) From: YAMAMOTO Takashi Add support to domain0 builder to load a (Net)BSD symtab for domain0. Signed-off-by: Christian Limpach --- xen/arch/x86/domain.c | 8 +++- xen/common/elf.c | 100 ++++++++++++++++++++++++++++++++++++++++ xen/include/xen/elf.h | 1 + xen/include/xen/sched.h | 5 ++ 4 files changed, 113 insertions(+), 1 deletion(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index d47910233a..aeb2b0c547 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -667,6 +667,9 @@ int construct_dom0(struct domain *p, if ( rc != 0 ) return rc; + if (dsi.load_bsd_symtab) + loadelfsymtab(image_start, 0, &dsi); + /* Set up domain options */ if ( dsi.use_writable_pagetables ) vm_assist(p, VMASST_CMD_enable, VMASST_TYPE_writable_pagetables); @@ -684,7 +687,7 @@ int construct_dom0(struct domain *p, * read-only). We have a pair of simultaneous equations in two unknowns, * which we solve by exhaustive search. */ - vinitrd_start = round_pgup(dsi.v_kernend); + vinitrd_start = round_pgup(dsi.v_end); vinitrd_end = vinitrd_start + initrd_len; vphysmap_start = round_pgup(vinitrd_end); vphysmap_end = vphysmap_start + (nr_pages * sizeof(unsigned long)); @@ -884,6 +887,9 @@ int construct_dom0(struct domain *p, /* Copy the OS image. */ (void)loadelfimage(image_start); + if (dsi.load_bsd_symtab) + loadelfsymtab(image_start, 1, &dsi); + /* Copy the initial ramdisk. */ if ( initrd_len != 0 ) memcpy((void *)vinitrd_start, initrd_start, initrd_len); diff --git a/xen/common/elf.c b/xen/common/elf.c index 8241d96520..7feb9095db 100644 --- a/xen/common/elf.c +++ b/xen/common/elf.c @@ -125,12 +125,18 @@ int parseelfimage(char *elfbase, if ( (p = strstr(guestinfo, "PT_MODE_WRITABLE")) != NULL ) dsi->use_writable_pagetables = 1; + + if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL ) + dsi->load_bsd_symtab = 1; + } dsi->v_kernstart = kernstart; dsi->v_kernend = kernend; dsi->v_kernentry = ehdr->e_entry; + dsi->v_end = dsi->v_kernend; + return 0; } @@ -155,3 +161,97 @@ int loadelfimage(char *elfbase) return 0; } + +#define ELFROUND (ELFSIZE / 8) + +int loadelfsymtab(char *elfbase, int doload, struct domain_setup_info *dsi) +{ + Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase, *sym_ehdr; + Elf_Shdr *shdr; + unsigned long maxva, symva; + char *p; + int h, i; + + maxva = (dsi->v_kernend + ELFROUND - 1) & ~(ELFROUND - 1); + symva = maxva; + maxva += sizeof(int); + dsi->symtab_addr = maxva; + dsi->symtab_len = 0; + maxva += sizeof(Elf_Ehdr) + ehdr->e_shnum * sizeof(Elf_Shdr); + maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1); + if (doload) { + p = (void *)symva; + + shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr)); + memcpy(shdr, elfbase + ehdr->e_shoff, ehdr->e_shnum * sizeof(Elf_Shdr)); + } else { + shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff); + p = NULL; /* XXX: gcc */ + } + + for ( h = 0; h < ehdr->e_shnum; h++ ) + { + if ( shdr[h].sh_type == SHT_STRTAB ) + { + /* Look for a strtab @i linked to symtab @h. */ + for ( i = 0; i < ehdr->e_shnum; i++ ) + if ( (shdr[i].sh_type == SHT_SYMTAB) && + (shdr[i].sh_link == h) ) + break; + /* Skip symtab @h if we found no corresponding strtab @i. */ + if ( i == ehdr->e_shnum ) + { + if (doload) { + shdr[h].sh_offset = 0; + } + continue; + } + } + + if ( (shdr[h].sh_type == SHT_STRTAB) || + (shdr[h].sh_type == SHT_SYMTAB) ) + { + if (doload) { + memcpy((void *)maxva, elfbase + shdr[h].sh_offset, + shdr[h].sh_size); + + /* Mangled to be based on ELF header location. */ + shdr[h].sh_offset = maxva - dsi->symtab_addr; + + } + dsi->symtab_len += shdr[h].sh_size; + maxva += shdr[h].sh_size; + maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1); + } + + if (doload) { + shdr[h].sh_name = 0; /* Name is NULL. */ + } + } + + if ( dsi->symtab_len == 0 ) + { + dsi->symtab_addr = 0; + goto out; + } + + if (doload) { + *(int *)p = maxva - dsi->symtab_addr; + sym_ehdr = (Elf_Ehdr *)(p + sizeof(int)); + memcpy(sym_ehdr, ehdr, sizeof(Elf_Ehdr)); + sym_ehdr->e_phoff = 0; + sym_ehdr->e_shoff = sizeof(Elf_Ehdr); + sym_ehdr->e_phentsize = 0; + sym_ehdr->e_phnum = 0; + sym_ehdr->e_shstrndx = SHN_UNDEF; + } + +#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK) /* XXX */ + + dsi->symtab_len = maxva - dsi->symtab_addr; + dsi->v_end = round_pgup(maxva); + + out: + + return 0; +} diff --git a/xen/include/xen/elf.h b/xen/include/xen/elf.h index f63daa6fc6..3a62173b1e 100644 --- a/xen/include/xen/elf.h +++ b/xen/include/xen/elf.h @@ -526,6 +526,7 @@ typedef struct { struct domain_setup_info; extern int loadelfimage(char *); +extern int loadelfsymtab(char *, int, struct domain_setup_info *); extern int parseelfimage(char *, unsigned long, struct domain_setup_info *); #endif /* __XEN_ELF_H__ */ diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 8f5345375b..4b7e7080c8 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -119,11 +119,16 @@ struct domain struct domain_setup_info { unsigned long v_start; + unsigned long v_end; unsigned long v_kernstart; unsigned long v_kernend; unsigned long v_kernentry; unsigned int use_writable_pagetables; + unsigned int load_bsd_symtab; + + unsigned long symtab_addr; + unsigned long symtab_len; }; #include /* for KERNEL_DS */ -- 2.30.2